// Implementation of a class to describe attributes of a model
// Copyright 2004 (C) Ralph Thomas

#include <model/attributeInfo.h>
#include <model/attributeNames.h>
#include <model/actionNames.h>
#include <vector>
#include <map>
#include <string>

namespace model {
	class attributeInfoImpl {
	  public:
		struct attrDesc {
			attrDesc( const std::string& name, bool settable )
			 : name( name ), settable( settable ) {}
			std::string name;	///< The name of an attribute
			bool settable;		///< Is the attribute settable
			bool operator==(const attrDesc& rhs) const {
				if( rhs.name != name ) return false;
				if( rhs.settable != settable ) return false;
				return true;
			}
		};
		typedef std::vector<attrDesc> attributeList;

		attributeList list;
	};

	attributeInfo::attributeInfo() : _impl( new attributeInfoImpl() ) {}
	attributeInfo::attributeInfo( const attributeInfo& ai )
	 : _impl( new attributeInfoImpl() ) {
		_impl->list = ai._impl->list;
	}

	attributeInfo::~attributeInfo() {
		delete _impl;
	}

	unsigned int attributeInfo::getNumberAttributes() const {
		return _impl->list.size();
	}

	const std::string& attributeInfo::getName( unsigned int i ) const {
		//
		// Ensure that the request is within bounds.
		//
		if( i >= _impl->list.size() ) return std::string();
		return _impl->list[i].name;
	}

	bool attributeInfo::getSettable( unsigned int i ) const {
		//
		// Ensure that the request is within bounds.
		//
		if( i >= _impl->list.size() ) return 0;
		return _impl->list[i].settable;
	}

	void attributeInfo::addAttribute( const std::string& name, bool settable ) {
		//
		// Check that we don't already have this attribute.
		//
		for( unsigned int i = 0; i < _impl->list.size(); i++ )
			if( _impl->list[i].name == name ) {
				_impl->list[i].settable = settable;
				return;
			}
		//
		// Add this record, we don't already have the name.
		//
		_impl->list.push_back( attributeInfoImpl::attrDesc( name, settable ) );
	}

	attributeInfo& attributeInfo::operator=( const attributeInfo& ai ) {
		_impl->list = ai._impl->list;
		return *this;
	}
	
	bool attributeInfo::operator==( const attributeInfo& rhs ) const {
		if( rhs._impl->list == _impl->list ) return true;
		return false;
	}
};

